package com.bwie.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.es.EsTbUser;
import com.bwie.poi.StringUtils;
import com.bwie.pojo.TbMenu;
import com.bwie.pojo.TbUser;
import com.bwie.service.TbUserService;
import com.bwie.mapper.TbUserMapper;
import com.bwie.utils.MD5Utils;
import com.bwie.utils.R;
import com.bwie.utils.Result;
import com.bwie.vo.PageInfoVo;
import com.bwie.vo.UserLoginVo;

import com.bwie.vo.UserPageInfo;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.apache.xmlbeans.impl.common.NameUtil;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* @author 叶雨洁
* @description 针对表【tb_user(用户表)】的数据库操作Service实现
* @createDate 2025-05-21 16:00:14
*/
@Service
@Slf4j
public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser>
    implements TbUserService{

    @Autowired
    TbUserMapper userMapper;

    @Autowired
    KafkaTemplate kafkaTemplate;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    FastFileStorageClient fastFileStorageClient;

    @Autowired
    HttpServletResponse response;

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public Result userLogin(UserLoginVo userLoginVo) {

        TbUser tbUser = userMapper.selectOne(
                new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserName, userLoginVo.getUserName())
        );
        if(tbUser==null){
            return Result.Error().setMsg("用户名不存在");
        }

        String encrypt = MD5Utils.encrypt(userLoginVo.getPassword());
        log.info("加密的密码是"+encrypt);

        if(!tbUser.getPassword().equals(encrypt)){
            return Result.Error().setMsg("用户密码错误");
        }


        String token = Jwts.builder().signWith(SignatureAlgorithm.HS256, "bwie")
                .claim("userId", tbUser.getUserId())
                .claim("password",tbUser.getPassword())
                .claim("nickName",tbUser.getNickName()).compact();

        String key="token-"+tbUser.getUserId();
        redisTemplate.opsForValue().set(key,token,60, TimeUnit.MINUTES);

        tbUser.setToken(token);


        return Result.OK().setData(tbUser).setMsg("登录成功");
    }

    @Override
    public R send(String message) {



        kafkaTemplate.send("topic-word",message);
        return R.OK();
    }


    @KafkaListener(topics = "topic-word")
    public void recordMessage(String message, Acknowledgment acknowledgment){

        System.out.println("kafka接收到消息"+message);

        acknowledgment.acknowledge();
    }

    @Override
    public R getMenuList(HttpServletRequest request) {


        String token = request.getHeader("token");
        if(token==null){
            return R.ERROR(500,"token为空请先登录");
        }

        Claims claims = Jwts.parser().setSigningKey("bwie").parseClaimsJws(token).getBody();
        Integer userId = claims.get("userId", Integer.class);

       List<TbMenu>menuList= userMapper.selectMenuList(userId);

        List<Tree<String>> build = TreeUtil.build(menuList, "0", (menu, tree) -> {
            tree.setName(menu.getMenuName());
            tree.setId(menu.getMenuId() + "");
            tree.setParentId(menu.getMenuPid() + "");
            tree.putExtra("path", menu.getMenuPath());
        });

        return R.OK(build);
    }

    @Override
    public R uploadImage(MultipartFile file)  {

        String url= null;
        try {
            String extName = FileNameUtil.extName(file.getOriginalFilename());

            StorePath storePath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(), extName, null);

            url = "http://192.168.80.192:8888/"+storePath.getFullPath();
            return R.OK(url);
        } catch (IOException e) {
            return R.ERROR(500,"上传失败");
        }


    }

    @Override
    public R userListPage(UserPageInfo userPageInfo) {


        Page<TbUser> tbUserPage = new Page<>(userPageInfo.getPageNum(),userPageInfo.getPageSize());

        QueryWrapper<TbUser> queryWrapper = new QueryWrapper<>();

        if(StringUtils.isNotEmpty(userPageInfo.getKeyWord())){
                    queryWrapper.lambda().like(TbUser::getUserName, userPageInfo.getKeyWord()).or()
                    .like(TbUser::getPhone, userPageInfo.getKeyWord()).or()
                    .like(TbUser::getUserEmail, userPageInfo.getKeyWord()).or()
                    .like(TbUser::getNickName,userPageInfo.getKeyWord());
        }

        if(userPageInfo.getGender()!=null){
            queryWrapper.lambda().eq(TbUser::getGender,userPageInfo.getGender());
        }

        if(userPageInfo.getStartTime()!=null){
            queryWrapper.lambda().gt(TbUser::getCreateTime,userPageInfo.getStartTime());
        }

        if(userPageInfo.getEndTime()!=null){
            queryWrapper.lambda().lt(TbUser::getCreateTime,userPageInfo.getEndTime());
        }

        Page<TbUser> tbUserPage1 = userMapper.selectPage(tbUserPage, queryWrapper);

        return R.OK(tbUserPage1);
    }

    @Override
    public R updateUserById(TbUser tbuser) {

        TbUser tbUser = userMapper.selectById(tbuser.getUserId());
        if(tbUser==null){
            return R.ERROR(500,"用户不存在");
        }


        userMapper.updateById(tbuser);
        return R.OK();
    }

    @Override
    public R deleteById(Integer userId) {

        TbUser tbUser = userMapper.selectById(userId);
        if(tbUser==null){
            return R.ERROR(500,"用户不存在");
        }


        userMapper.deleteById(userId);
        return R.OK();
    }

    @Override
    public R DeleteAll(List<TbUser> userlist) {

        List<TbUser> tbUsers = userMapper.selectList(null);

        if(tbUsers==null){
            return R.ERROR(500,"用户为空");
        }

        for (TbUser tbUser : userlist) {
            userMapper.deleteById(tbUser.getUserId());
        }


        return R.OK("删除成功");
    }

    @Override
    public R checkStatus(TbUser tbUser) {

        if(tbUser.getUserStatus()==2){
            if(StringUtils.isEmpty(tbUser.getReason())){

                return R.ERROR(500,"审核驳回请给出原因");
            }
        }

        TbUser tbUser1 = userMapper.selectById(tbUser.getUserId());
        if(tbUser1==null){
            return R.ERROR(500,"用户不存在");
        }

        tbUser1.setUserStatus(tbUser.getUserStatus());
        tbUser1.setReason(tbUser.getReason());
        userMapper.updateById(tbUser);

        return R.OK();
    }



    @Override
    public R createIndex() {

        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(EsTbUser.class);
        boolean exists = indexOperations.exists();

        //判断索引是否存在
        if(exists){
            indexOperations.delete();
        }
           //不存在则创建索引
            indexOperations.create();
          //创建映射
        Document mapping = indexOperations.createMapping();
        indexOperations.putMapping(mapping);
        return R.OK();
    }
    @Override
    public R synMysql() {

        //首先获取列表数据
        List<TbUser> userList = userMapper.selectList(null);
        //遍历并转换es类型
        userList.stream().forEach(item->{
            EsTbUser esTbUser = BeanUtil.toBean(item, EsTbUser.class);
            elasticsearchRestTemplate.save(esTbUser);   //同步进es里
        });
        return R.OK();
    }

    @Override
    public R esUserList(PageInfoVo pageInfoVo) {

        Integer pageNum=0;
        if(pageInfoVo.getPageNum()>0){
            pageNum=pageInfoVo.getPageNum()-1;
        }
        //构造分页参数
        PageRequest request = PageRequest.of(pageNum, pageInfoVo.getPageSize());

        //构造查询条件
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        if(StringUtils.isNotEmpty(pageInfoVo.getKeyWord())){
            boolQueryBuilder.should(QueryBuilders.fuzzyQuery("userName",pageInfoVo.getKeyWord()));
            boolQueryBuilder.should(QueryBuilders.fuzzyQuery("nickName",pageInfoVo.getKeyWord()));
        }

        HighlightBuilder highlightBuilder = new HighlightBuilder()
                .preTags("<font color='red'>")
                .postTags("</font>")
                .field("userName")
                .field("nickName");

        //开始执行查询
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(boolQueryBuilder)
                .withPageable(request)
                .withHighlightBuilder(highlightBuilder);

        SearchHits<EsTbUser> searchHits = elasticsearchRestTemplate.search(builder.build(), EsTbUser.class);

        long total = searchHits.getTotalHits();

        ArrayList<EsTbUser> records = new ArrayList<>();

        searchHits.stream().forEach(item->{
            EsTbUser esTbUser = item.getContent();

            List<String> userNameList = item.getHighlightField("userName");
            if(StringUtils.isNotEmpty(userNameList)){
                esTbUser.setUserName(userNameList.get(0));
            }
            List<String> nickNameList = item.getHighlightField("nickName");
            if(StringUtils.isNotEmpty(nickNameList)){
                esTbUser.setNickName(nickNameList.get(0));
            }

            records.add(esTbUser);
        });

        HashMap<String, Object> hashMap = new HashMap<>();

        hashMap.put("total",total);
        hashMap.put("records",records);

        return R.OK(hashMap);
    }

}




